﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace WCYCReader.Utility.SocketHelper
{
    /// <summary>
    /// 提供获取手机的 IP 地址的静态方法，原作者文章的网址：
    /// http://blogs.msdn.com/b/andypennell/archive/2011/08/11/finding-your-own-ip-address-on-windows-phone-mango.aspx
    /// </summary>
    public class MyIPAddress
    {
        #region 仅适用于 WP8
        public static IPAddress Find()
        {
            List<string> ipAddresses = new List<string>();

            var hostnames = Windows.Networking.Connectivity.NetworkInformation.GetHostNames();
            foreach (var hn in hostnames)
            {
                if (hn.IPInformation != null)
                {
                    string ipAddress = hn.DisplayName;
                    ipAddresses.Add(ipAddress);
                }
            }

            IPAddress address = IPAddress.Parse(ipAddresses[0]);
            return address;
        }
        #endregion


        #region WP7 也适用
        // 调用方法
        //private void button1_Click()
        //{
        //    MyIPAddress finder = new MyIPAddress();
        //    finder.Find((address) =>
        //    {
        //        Dispatcher.BeginInvoke(() =>
        //        {
        //            string str = address == null ? "Unknown" : address.ToString();
        //        });
        //    });
        //}

        Action<IPAddress> FoundCallback;
        UdpAnySourceMulticastClient MulticastSocket;
        const int PortNumber = 50000;       // pick a number, any number
        string MulticastMessage = "FIND-MY-IP-PLEASE" + new Random().Next().ToString();
 
        public void Find(Action<IPAddress> callback)
        {
            FoundCallback = callback;
 
            MulticastSocket = new UdpAnySourceMulticastClient(IPAddress.Parse("239.255.255.250"), PortNumber);
            MulticastSocket.BeginJoinGroup((result) =>
            {
                try
                {
                    MulticastSocket.EndJoinGroup(result);
                    GroupJoined(result);
                }
                catch (Exception ex)
                {
                    //Debug.WriteLine("EndjoinGroup exception {0}", ex.Message);
                    // This can happen eg when wifi is off
                    FoundCallback(null);
                }
            },
                null);
        }
 
        void callback_send(IAsyncResult result)
        {
        }
 
        byte[] MulticastData;
        bool keepsearching;
 
        void GroupJoined(IAsyncResult result)
        {
            MulticastData = Encoding.UTF8.GetBytes(MulticastMessage);
            keepsearching = true;
            MulticastSocket.BeginSendToGroup(MulticastData, 0, MulticastData.Length, callback_send, null);
 
            while (keepsearching)
            {
                try
                {
                    byte[] buffer = new byte[MulticastData.Length];
                    MulticastSocket.BeginReceiveFromGroup(buffer, 0, buffer.Length, DoneReceiveFromGroup, buffer);
                }
                catch (Exception ex)
                {
                    //Debug.WriteLine("Stopped Group read due to " + ex.Message);
                    keepsearching = false;
                }
            }
        }
 
        void DoneReceiveFromGroup(IAsyncResult result)
        {
            try
            {
                IPEndPoint where;
                int responselength = MulticastSocket.EndReceiveFromGroup(result, out where);
                byte[] buffer = result.AsyncState as byte[];
                if (responselength == MulticastData.Length && buffer.SequenceEqual(MulticastData))
                {
                    //Debug.WriteLine("FOUND myself at " + where.Address.ToString());
                    keepsearching = false;
                    FoundCallback(where.Address);
                }
            }
            catch
            {

            }
        }

        #endregion 
    }
}
